package com.x.provider.general.service.cms;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.x.core.utils.BeanUtil;
import com.x.kafka.MqTemplate;
import com.x.provider.api.common.enums.ItemTypeEnum;
import com.x.provider.api.general.constants.GeneralEventTopic;
import com.x.provider.api.general.enums.CustomerStarRelationEnum;
import com.x.provider.api.general.model.dto.cms.StarListReqDTO;
import com.x.provider.api.general.model.dto.cms.StarSaveReqDTO;
import com.x.provider.api.general.model.dto.cms.CommentDTO;
import com.x.provider.api.general.model.event.StarEvent;
import com.x.provider.general.mapper.StarMapper;
import com.x.provider.general.model.domain.cms.Comment;
import com.x.provider.general.model.domain.cms.Star;
import com.x.provider.general.model.query.cms.StarQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class StarServiceImpl implements StarService {

    private final StarMapper starMapper;
    private final MqTemplate mqTemplate;
    private final ItemStatService itemStatService;
    private final CommentStatService commentStatService;
    private final CommentService commentService;

    public StarServiceImpl(StarMapper starMapper,
                           MqTemplate mqTemplate,
                           ItemStatService itemStatService,
                           CommentStatService commentStatService,
                           CommentService commentService){
        this.starMapper = starMapper;
        this.mqTemplate = mqTemplate;
        this.itemStatService = itemStatService;
        this.commentStatService = commentStatService;
        this.commentService = commentService;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean star(StarSaveReqDTO starSaveReqDTO) {
        if (starSaveReqDTO.getStar() == null){
            return false;
        }
        Comment comment = null;
        if (starSaveReqDTO.getItemType() == ItemTypeEnum.COMMENT.getValue()){
            comment = commentService.getById(starSaveReqDTO.getItemId());
            if (comment == null){
                return false;
            }
        }
        commentStatService.onStar(starSaveReqDTO);
        itemStatService.onStar(starSaveReqDTO);
        return true;
    }

    @Override
    public boolean isStarred(Integer itemType, Long itemId, Long customerId){
        Star star = getStar(itemId, customerId, itemType);
        return star != null && star.getStar();
    }

    @Override
    public List<Star> listStar(StarListReqDTO starListReqDTO) {
        LambdaQueryWrapper<Star> query = buildQuery(StarQuery.builder().starCustomerId(starListReqDTO.getStarCustomerId()).itemType(starListReqDTO.getItemType())
                .itemIdList(starListReqDTO.getItemIdList()).build());
        return starMapper.selectList(query);
    }

    @Override
    public Map<Long, Integer> listStarRelation(StarListReqDTO starListReqDTO) {
        Set<Long> starCustomerIdSet = listStar(StarQuery.builder().starCustomerId(starListReqDTO.getStarCustomerId()).itemIdList(starListReqDTO.getItemIdList())
                .itemType(ItemTypeEnum.CUSTOMER.getValue()).star(true).build()).stream().map(item -> item.getItemId()).collect(Collectors.toSet());
        Set<Long> beStarCustomerIdSet = listStar(StarQuery.builder().starCustomerIdList(starListReqDTO.getItemIdList()).itemType(ItemTypeEnum.CUSTOMER.getValue())
                .itemId(starListReqDTO.getStarCustomerId()).star(true).build()).stream().map(item -> item.getStarCustomerId()).collect(Collectors.toSet());
        Map<Long, Integer> result = new HashMap<>(starListReqDTO.getItemIdList().size());
        starListReqDTO.getItemIdList().stream().forEach(item ->{
            result.put(item, toStarRelation(starCustomerIdSet.contains(item), beStarCustomerIdSet.contains(item)));
        });
        return result;
    }

    private Integer toStarRelation(Boolean star, Boolean beStar){
        if (!star && !beStar){
            return CustomerStarRelationEnum.NO_RELATION.getValue();
        }
        if (star && beStar){
            return CustomerStarRelationEnum.EACH_OTHER_STAR.getValue();
        }
        if (star){
            return CustomerStarRelationEnum.STAR.getValue();
        }
        return CustomerStarRelationEnum.BE_STAR.getValue();
    }
    private Star getStar(Long itemId, Long starCustomerId, Integer itemType){
        LambdaQueryWrapper<Star> query = buildQuery(StarQuery.builder().itemId(itemId).starCustomerId(starCustomerId).itemType(itemType).build());
        return starMapper.selectOne(query);
    }

    private List<Star> listStar(StarQuery query){
        return starMapper.selectList(buildQuery(query));
    }

    private LambdaQueryWrapper<Star> buildQuery(StarQuery startQuery) {
        LambdaQueryWrapper<Star> query = new LambdaQueryWrapper<>();
        if (startQuery.getItemId() != null){
            query = query.eq(Star::getItemId, startQuery.getItemId());
        }
        if (startQuery.getStarCustomerId() != null){
            query = query.eq(Star::getStarCustomerId, startQuery.getStarCustomerId());
        }
        if (startQuery.getItemType() != null){
            query = query.eq(Star::getItemType, startQuery.getItemType());
        }
        if (!CollectionUtils.isEmpty(startQuery.getItemIdList())){
            query = query.in(Star::getItemId, startQuery.getItemIdList());
        }
        if (!CollectionUtils.isEmpty(startQuery.getStarCustomerIdList())){
            query = query.in(Star::getStarCustomerId, startQuery.getStarCustomerIdList());
        }
        if (startQuery.getStar() != null){
            query = query.eq(Star::getStar, startQuery.getStar());
        }
        return query;
    }
}
